package com.ququ.syb.business.payment.service;

import com.ququ.common.result.Result;
import com.ququ.common.utils.RegExpUtil;
import com.ququ.syb.business.payment.fegin.AccountFegin;
import com.ququ.syb.business.payment.fegin.CommissionFegin;
import com.ququ.syb.business.payment.fegin.PayChannelFegin;
import com.ququ.syb.business.payment.fegin.PayOrderFegin;
import com.ququ.syb.business.payment.redis.RedisDao;
import com.ququ.syb.common.constant.PayOrderStatusConstant;
import com.ququ.syb.common.constant.PayOrderTypeConstant;
import com.ququ.syb.common.constant.RedisKeyConstant;
import com.ququ.syb.common.constant.ResultStatusConstant;
import com.ququ.syb.common.pojo.AccountInfo;
import com.ququ.syb.common.pojo.PayChannel;
import com.ququ.syb.common.pojo.PayOrder;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;

@Service
public class PayOrderService {

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private Logger logger = LoggerFactory.getLogger(PayOrderService.class);

    @Autowired
    private PayOrderFegin payOrderFegin;
    @Autowired
    private PayChannelFegin payChannelFegin;
    @Autowired
    private CommissionFegin commissionFegin;
    @Autowired
    private AccountFegin accountFegin;
    @Autowired
    private RedisDao redisDao;


    /**
     * 创建支付订单
     * @param orderno               商户订单号
     * @param amount                订单金额，单位为分
     * @param ordertype             订单类型: 0-普通订单 1-担保订单 2-代收订单
     * @param title                 订单标题
     * @param desc                  订单商户信息
     * @param returnurl             网页同步跳转网址
     * @param callbackurl           异步回调地址
     * @param withdrawcallbackurl   直清提现回调地址
     * @param payaccountid          付款人商户号
     * @param payeeaccountid        收款人商户号
     * @param paycommission         自定义手续费，付款人手续费金额，单位为分
     * @param payeecommission       自定义手续费，收款人手续费金额，单位为分
     * @param appcode               应用代码
     * @param paychannelid          支付通道号
     * @param assureday             担保天数，担保订单参数，默认为7天
     * @param timeout               订单超时，非担保订单时用于自动关闭订单
     * @param divideinfo            分账信息
     * @return
     */
    public Result<PayOrder> createPayOrder(String orderno, Long amount, Integer ordertype, String title, String desc, String returnurl, String callbackurl,
                                           String withdrawcallbackurl, String payaccountid, String payeeaccountid, Long paycommission, Long payeecommission,
                                           String appcode, String paychannelid, Integer assureday, Integer timeout, String divideinfo){

        Jedis jedis = redisDao.getJedis();
        try {
            //校验参数合法性
            if (StringUtils.isBlank(orderno))
                return new Result<>(-1, "支付订单商户订单号不可为空");
            Result<PayChannel> payChannelResult = payChannelFegin.getPayChannel(paychannelid, payeeaccountid, appcode);
            if (payChannelResult.getStatus() != ResultStatusConstant.SUCCESS)
                return new Result<>(payChannelResult.getStatus(), payChannelResult.getMsg());
            PayChannel payChannel = payChannelResult.getData();
            if (amount == null)
                return new Result<>(-1, "订单金额不可为空");
            if (amount < payChannel.getMinpayamount().multiply(new BigDecimal(100)).longValue())
                return new Result<>(-1, "订单金额小于通道单笔下限" + payChannel.getMinpayamount() + "元");
            if (amount > payChannel.getMaxpayamount() * 100l)
                return new Result<>(-1, "订单金额大于通道单笔上限" + payChannel.getMaxpayamount() + "元");
            if (ordertype == null)
                return new Result<>(-1, "订单类型不可为空");
            if (ordertype < PayOrderTypeConstant.ORDINARY || ordertype > PayOrderTypeConstant.PAYTOCARD)
                return new Result<>(-1, "订单类型不正确");
            if (ordertype == PayOrderTypeConstant.COLLECTION && StringUtils.isBlank(payaccountid))
                payaccountid = payeeaccountid;          //代收订单，付款人与收款人全部设置为本人
            if (StringUtils.isBlank(title))
                return new Result<>(-1, "订单标题不可为空");
            if (StringUtils.isBlank(desc))
                desc = title;
            if (StringUtils.isNotBlank(returnurl) && !(returnurl.startsWith("http://") || returnurl.startsWith("https://")))
                return new Result<>(-1, "支付回跳页面网址格式不正确");
            if (StringUtils.isBlank(callbackurl) || !(callbackurl.startsWith("http://") || callbackurl.startsWith("https://")))
                return new Result<>(-1, "支付回调地址不可为空或格式不正确");
            //检查收付款双方账户状态
            if (ordertype != PayOrderTypeConstant.COLLECTION) {
                AccountInfo payer = accountFegin.getAccountInfo(payaccountid).getData();
                if (payer == null || payer.getStatus() != 1)
                    return new Result<>(-1, "付款方账户不存在或不可用");
            }
            AccountInfo payee = accountFegin.getAccountInfo(payeeaccountid).getData();
            if (payee == null || payee.getStatus() != 1)
                return new Result<>(-1, "收款方账户不存在或不可用");
            boolean defineCommission = false;
            if (payChannel.getAllowdefinecommission() != null && payChannel.getAllowdefinecommission() == 1) {
                if (paycommission != null || payeecommission != null) {
                    //自定义手续费
                    paycommission = paycommission == null ? 0l : paycommission;
                    payeecommission = payeecommission == null ? 0l : payeecommission;
                    defineCommission = true;
                }
            }else {
                paycommission = paycommission == null ? 0l : paycommission;
            }
            if (!defineCommission) {     //默认手续费为卖方
                paycommission = paycommission == null ? 0l : paycommission;
                Long totalcommission = commissionFegin.getPayCommission(amount, paychannelid, appcode, payeeaccountid, null).getData();
                payeecommission = (totalcommission - paycommission)>=0L?totalcommission - paycommission:0L;
            }
            if (ordertype == PayOrderTypeConstant.ASSURE) {
                if (payChannel.getAllowassure() == null || payChannel.getAllowassure() == 0)
                    return new Result<>(-1, "本通道不支持担保订单");
                assureday = assureday == null ? 7 : assureday;    //担保订单，不传参数时默认自动担保时间为7天
            }
            timeout = timeout == null ? 24 * 60 : timeout;
            if (StringUtils.isNotBlank(divideinfo) && (payChannel.getAllowdivide() == null || payChannel.getAllowdivide() == 0))
                return new Result<>(-1, "本通道不支持分账订单");
            Long costcommission = commissionFegin.getPayCostCommissionRate(amount, paychannelid).getData();
            //生成订单
            PayOrder payOrder = new PayOrder();
            payOrder.setOutorderno(orderno);
            payOrder.setAppcode(appcode);
            payOrder.setAmount(amount);
            payOrder.setType(ordertype);
            payOrder.setPaychannelid(paychannelid);
            payOrder.setCreatetime(new Date());
            payOrder.setCreateaccount(payaccountid);
            payOrder.setPayeeaccount(payeeaccountid);
            payOrder.setPaycommission(paycommission==null?0L:paycommission);
            payOrder.setPayeecommission(payeecommission==null?0L:payeecommission);
            payOrder.setStatus(PayOrderStatusConstant.DEFAULT);
            payOrder.setTitle(title);
            payOrder.setDescription(desc);
            payOrder.setCallbackurl(callbackurl);
            payOrder.setReturnurl(returnurl);
            payOrder.setTimeout(new Date());
            payOrder.getTimeout().setTime(payOrder.getCreatetime().getTime() + timeout * 60l * 1000l);
            payOrder.setCostcommission(costcommission==null?0L:costcommission);
            payOrder.setWithdrawcallbackurl(withdrawcallbackurl);
            payOrder.setDivideinfo(divideinfo);
            if (ordertype == PayOrderTypeConstant.ASSURE) {
                payOrder.setDefaultfinshtime(new Date());
                payOrder.getDefaultfinshtime().setTime(payOrder.getCreatetime().getTime() + assureday * 24l * 3600l * 1000l);
                payOrder.setTimeout(payOrder.getDefaultfinshtime());
            }
            logger.debug("保存之前的订单内容:{}", payOrder);
            payOrder = payOrderFegin.save(payOrder).getData();
            logger.debug("保存入库之后的订单内容:{}", payOrder);
            //保存订单超时数据到Redis
            jedis.setex(RedisKeyConstant.PAYORDER_TIMEOUT + payOrder.getTradenum(), ordertype == PayOrderTypeConstant.ASSURE ? assureday * 24 * 3600 : timeout * 60, simpleDateFormat.format(payOrder.getTimeout()));
            jedis.sadd(RedisKeyConstant.PAYORDER_TIMEOUT_SET, payOrder.getTradenum());
            return new Result<>(payOrder);
        }catch (Exception e){
            logger.error("订单创建异常",e);
            return new Result<>(9999,"订单创建异常:"+e.getMessage());
        }finally {
            redisDao.close(jedis);
        }
    }



}
